{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "19c4f427",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "dfbfcf7c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x17422603b50>]"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "x = np.linspace(0, 10, 50)\n",
    "\n",
    "y = 0.8 * x - 5\n",
    "plt.plot(x, y, color='red')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "c81830c4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x20eb3271730>]"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "x = np.linspace(0, 10, 50)\n",
    "\n",
    "y = x**2 + 4*x - 15\n",
    "\n",
    "plt.plot(x, y)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1a50c07e",
   "metadata": {},
   "source": [
    "最小二乘法可以将误差方程转化为有确定解的代数方程组（其方程式数目正好等于未知数的个数），从而可求解出这些未知参数，这个有确定解的代数方程组称为最小二乘法估计的正规方程，公式如下：\n",
    "\n",
    "$ \\theta = (X^{T}X)^{-1}X^{T} y $ 或者 $ W = (X^{T}X)^{-1} X^{T} y $，其中的W、$ \\theta $ 即是方程的解！\n",
    "\n",
    "###### 最小二乘法公式：\n",
    "$J(\\theta) = \\frac{1}{2}\\sum_{i=0}^n(h_{\\theta}(x_i)-y_i)^2 $\n",
    "\n",
    "使用矩阵表示：\n",
    "（二者等效）\n",
    "\n",
    "$ J(\\theta) = \\frac{1}{2}\\sum_{i=0}^n(h_{\\theta(x_i)}-y)(h_{\\theta(x_i)}-y) $\n",
    "\n",
    "矩阵操作\n",
    "\n",
    "$ J(\\theta) = \\frac{1}{2}(X{\\theta}-y)^{T}(X{\\theta}-y) $"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "348ff15a",
   "metadata": {},
   "source": [
    "### 线性回归举例\n",
    "\n",
    "$\n",
    "\\begin{cases}\n",
    "x + y = 14 \\\\\n",
    "2x - y = 10 \\\\\n",
    "\\end{cases}\n",
    "$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dc64dfbb",
   "metadata": {},
   "source": [
    "### 2 正规方程"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "e0cefd56",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1,  1],\n",
       "       [ 2, -1]])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = np.array([[1, 1],[2, -1]])\n",
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "b264de82",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([14, 10])"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y = np.array([14, 10])\n",
    "y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "8dfc82fa",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([8., 6.])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linalg.solve(x, y)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eb3e1ea0",
   "metadata": {},
   "source": [
    "$ f(x, y) = 8x + 6y $\n",
    "\n",
    "$ W = (X^{T}X)^{-1} X^{T} y $"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "999b0f11",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 5, -1],\n",
       "       [-1,  2]])"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x.T.dot(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "f4a3dc97",
   "metadata": {},
   "outputs": [],
   "source": [
    "A = x.T.dot(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "6c9fbf9f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.22222222, 0.11111111],\n",
       "       [0.11111111, 0.55555556]])"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 逆矩阵\n",
    "B = np.linalg.inv(A)\n",
    "B"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "c4b990aa",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.33333333,  0.33333333],\n",
       "       [ 0.66666667, -0.33333333]])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "C = B.dot(x.T)\n",
    "C"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "a094cf6a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([8., 6.])"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "C.dot(y)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fa72c0a1",
   "metadata": {},
   "source": [
    "#### 三元一次方程计算\n",
    "\n",
    "$\n",
    "\\begin{cases}\n",
    "x - y + z = 100 \\\\\n",
    "2x + y - z = 80 \\\\\n",
    "3x - 2y + 6z = 256 \\\\\n",
    "\\end{cases}\n",
    "$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "9c4adcaf",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1, -1,  1],\n",
       "       [ 2,  1, -1],\n",
       "       [ 3, -2,  6]])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X = np.array([[1, -1, 1],[2, 1, -1],[3, -2, 6]])\n",
    "X"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "752c3767",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([100,  80, 256])"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y = np.array([100, 80, 256])\n",
    "y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "6dcc5ed9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 60., -41.,  -1.])"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "W = np.linalg.inv(X.T.dot(X)).dot(X.T).dot(y)\n",
    "W"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d6e028d5",
   "metadata": {},
   "source": [
    "### sklearn算法使用（正规方程）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "8b48b5ba",
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.linear_model import LinearRegression"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "db3cf6fd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1, -1,  1],\n",
       "       [ 2,  1, -1],\n",
       "       [ 3, -2,  6]])"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "array([100,  80, 256])"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "array([ 60., -41.,  -1.])"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# fit_intercept = False 不计算截距\n",
    "model = LinearRegression(fit_intercept = False)\n",
    "\n",
    "# X 数据，y 目标值\n",
    "display(X, y)\n",
    "model.fit(X, y)\n",
    "\n",
    "# coef_ 结果，返回值\n",
    "# 系数，斜率，W，方程的解\n",
    "model.coef_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "8693e1f6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.0"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 默认计算截距\n",
    "model.intercept_"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "085dd572",
   "metadata": {},
   "source": [
    "### 带截距的线性方程"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4e73dcf7",
   "metadata": {},
   "source": [
    "加上截距12\n",
    "\n",
    "$\n",
    "f(X) = 60x_{1} - 41x_{2} - x_{3} + 12\n",
    "$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "9698d4cc",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([112,  92, 268])"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y = y + 12\n",
    "y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "c47c86c6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>#sk-container-id-2 {color: black;background-color: white;}#sk-container-id-2 pre{padding: 0;}#sk-container-id-2 div.sk-toggleable {background-color: white;}#sk-container-id-2 label.sk-toggleable__label {cursor: pointer;display: block;width: 100%;margin-bottom: 0;padding: 0.3em;box-sizing: border-box;text-align: center;}#sk-container-id-2 label.sk-toggleable__label-arrow:before {content: \"▸\";float: left;margin-right: 0.25em;color: #696969;}#sk-container-id-2 label.sk-toggleable__label-arrow:hover:before {color: black;}#sk-container-id-2 div.sk-estimator:hover label.sk-toggleable__label-arrow:before {color: black;}#sk-container-id-2 div.sk-toggleable__content {max-height: 0;max-width: 0;overflow: hidden;text-align: left;background-color: #f0f8ff;}#sk-container-id-2 div.sk-toggleable__content pre {margin: 0.2em;color: black;border-radius: 0.25em;background-color: #f0f8ff;}#sk-container-id-2 input.sk-toggleable__control:checked~div.sk-toggleable__content {max-height: 200px;max-width: 100%;overflow: auto;}#sk-container-id-2 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {content: \"▾\";}#sk-container-id-2 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-2 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-2 input.sk-hidden--visually {border: 0;clip: rect(1px 1px 1px 1px);clip: rect(1px, 1px, 1px, 1px);height: 1px;margin: -1px;overflow: hidden;padding: 0;position: absolute;width: 1px;}#sk-container-id-2 div.sk-estimator {font-family: monospace;background-color: #f0f8ff;border: 1px dotted black;border-radius: 0.25em;box-sizing: border-box;margin-bottom: 0.5em;}#sk-container-id-2 div.sk-estimator:hover {background-color: #d4ebff;}#sk-container-id-2 div.sk-parallel-item::after {content: \"\";width: 100%;border-bottom: 1px solid gray;flex-grow: 1;}#sk-container-id-2 div.sk-label:hover label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-2 div.sk-serial::before {content: \"\";position: absolute;border-left: 1px solid gray;box-sizing: border-box;top: 0;bottom: 0;left: 50%;z-index: 0;}#sk-container-id-2 div.sk-serial {display: flex;flex-direction: column;align-items: center;background-color: white;padding-right: 0.2em;padding-left: 0.2em;position: relative;}#sk-container-id-2 div.sk-item {position: relative;z-index: 1;}#sk-container-id-2 div.sk-parallel {display: flex;align-items: stretch;justify-content: center;background-color: white;position: relative;}#sk-container-id-2 div.sk-item::before, #sk-container-id-2 div.sk-parallel-item::before {content: \"\";position: absolute;border-left: 1px solid gray;box-sizing: border-box;top: 0;bottom: 0;left: 50%;z-index: -1;}#sk-container-id-2 div.sk-parallel-item {display: flex;flex-direction: column;z-index: 1;position: relative;background-color: white;}#sk-container-id-2 div.sk-parallel-item:first-child::after {align-self: flex-end;width: 50%;}#sk-container-id-2 div.sk-parallel-item:last-child::after {align-self: flex-start;width: 50%;}#sk-container-id-2 div.sk-parallel-item:only-child::after {width: 0;}#sk-container-id-2 div.sk-dashed-wrapped {border: 1px dashed gray;margin: 0 0.4em 0.5em 0.4em;box-sizing: border-box;padding-bottom: 0.4em;background-color: white;}#sk-container-id-2 div.sk-label label {font-family: monospace;font-weight: bold;display: inline-block;line-height: 1.2em;}#sk-container-id-2 div.sk-label-container {text-align: center;}#sk-container-id-2 div.sk-container {/* jupyter's `normalize.less` sets `[hidden] { display: none; }` but bootstrap.min.css set `[hidden] { display: none !important; }` so we also need the `!important` here to be able to override the default hidden behavior on the sphinx rendered scikit-learn.org. See: https://github.com/scikit-learn/scikit-learn/issues/21755 */display: inline-block !important;position: relative;}#sk-container-id-2 div.sk-text-repr-fallback {display: none;}</style><div id=\"sk-container-id-2\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>LinearRegression()</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item\"><div class=\"sk-estimator sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-2\" type=\"checkbox\" checked><label for=\"sk-estimator-id-2\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">LinearRegression</label><div class=\"sk-toggleable__content\"><pre>LinearRegression()</pre></div></div></div></div></div>"
      ],
      "text/plain": [
       "LinearRegression()"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 指定了fit_intercept = True参数，就没有使用正规方程\n",
    "model = LinearRegression(fit_intercept = True)\n",
    "\n",
    "# fit 训练，特指算法、模型训练，拟合\n",
    "# 数据X和y之间存在规律，拟合出来\n",
    "# display(X, y)\n",
    "model.fit(X, y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "1aa9df6c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "72.28235294117653"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 截距\n",
    "b_ = model.intercept_\n",
    "b_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "ba7cfc6c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([19.81176471,  4.21176471, 24.11764706])"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\n",
    "w_ = model.coef_\n",
    "w_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "934f8575",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([112.,  92., 268.])"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X.dot(w_) + b_"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5b512abd",
   "metadata": {},
   "source": [
    "#### 修改数据X"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "86b8a2ee",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1, -1,  1,  1],\n",
       "       [ 2,  1, -1,  1],\n",
       "       [ 3, -2,  6,  1]])"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "array([112,  92, 268])"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 添加一列系数 W0，y增加了12\n",
    "X = np.concatenate([X, np.full(shape=(3,1),fill_value=1)], axis=1)\n",
    "display(X, y)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1ec827e8",
   "metadata": {},
   "source": [
    "> 此处问题下一章解决"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "41807a96",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
